#pragma once
#include <math.h>
#include "../Core/Vector.h"
#include "DrawAutomaticUniform.h"
#include "Uniform.h"
#include "Context.h"
#include "DrawCommand.h"
#include "SceneState.h"

using namespace Core;

namespace Renderer
{
	class WindowToWorldNearPlaneUniform : public DrawAutomaticUniform
	{
	public:
		WindowToWorldNearPlaneUniform(Uniform* uniform)
		{
			_uniform = (TemplateUniform<Matrix4F>*)uniform;
		}

		void Set(Context* context, DrawCommand* drawCommand, SceneState* sceneState)
		{
			auto camera = sceneState->GetCamera();
			double theta = camera->FieldOfViewX() * 0.5;
			double phi = camera->FieldOfViewY() * 0.5;
			double nearDistance = camera->PerspectiveNearPlaneDistance();

			//
			// Coordinate system for the near plane:  origin is at center, x and y
			// span [-1, 1] just like noramlized device coordinates.
			//
			Vector3D origin = camera->Eye() + (nearDistance * camera->Forward());    // Project eye onto near plane
			Vector3D xAxis = camera->Right() * (nearDistance *tan(theta));  // Rescale right to near plane
			Vector3D yAxis = camera->Up() * (nearDistance * tan(phi));       // Rescale up to near plane

			_uniform->SetValue(Matrix4F(
				xAxis.x, yAxis.x, 0.0, origin.x,
				xAxis.y, yAxis.y, 0.0, origin.y,
				xAxis.z, yAxis.z, 0.0, origin.z,
				0.0, 0.0, 0.0, 1.0));
		}

	private:
		TemplateUniform<Matrix4F>* _uniform;
	};
}